package pdh

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"

	"github.com/shirou/gopsutil/net"
)

const (
	KB = 1024
	MB = KB * 1024
	GB = MB * 1024
)

// DataSize 字节的单位转换 保留两位小数
func DataSize(s int) (size string) {
	if s < 1024 {
		//return strconv.FormatInt(s, 10) + "B"
		return fmt.Sprintf("%.2f B", float64(s)/float64(1))
	} else if s < (1024 * 1024) {
		return fmt.Sprintf("%.2f KB", float64(s)/float64(1024))
	} else if s < (1024 * 1024 * 1024) {
		return fmt.Sprintf("%.2f MB", float64(s)/float64(1024*1024))
	} else if s < (1024 * 1024 * 1024 * 1024) {
		return fmt.Sprintf("%.2f GB", float64(s)/float64(1024*1024*1024))
	} else if s < (1024 * 1024 * 1024 * 1024 * 1024) {
		return fmt.Sprintf("%.2f TB", float64(s)/float64(1024*1024*1024*1024))
	} else { //if s < (1024 * 1024 * 1024 * 1024 * 1024 * 1024)
		return fmt.Sprintf("%.2f EB", float64(s)/float64(1024*1024*1024*1024*1024))
	}
}

// WaitForAppQuitSignal like C int atexit (void (*)(void))
func WaitForAppQuitSignal(forever bool, f func(sign os.Signal)) {
	signalFunc := func() {
		defer func() {
			_ = recover()
		}()

		quitChan := make(chan os.Signal, 2)
		signal.Notify(quitChan,
			syscall.SIGINT,
			syscall.SIGTERM,
			syscall.SIGHUP,
		)

		s := <-quitChan

		f(s)
	}

	if forever {
		signalFunc()
	} else {
		go signalFunc()
	}
}

// NetConnectionsPid pid的网络连接(pid为0代表所有进程的网络连接信息)
func NetConnectionsPid(pid int32) ([]net.ConnectionStat, error) {
	if pid <= 0 {
		pid = 0
	}
	connections, err := net.ConnectionsPid("all", pid)

	/*
		type ConnectionStat struct {
			Fd     uint32  `json:"fd"`
			Family uint32  `json:"family"`      //
			Type   uint32  `json:"type"`        // 1: TCP, 2: UDP
			Laddr  Addr    `json:"localaddr"`
			Raddr  Addr    `json:"remoteaddr"`
			Status string  `json:"status"`      // TCP: LISTEN/ESTABLISHED/CLOSE_WAIT  UDP:
			Uids   []int32 `json:"uids"`
			Pid    int32   `json:"pid"`         // process id
		}
	*/

	return connections, err
}

const (
	Total = "_Total"
)

type CounterType string

const (
	CounterTypeProcessor        CounterType = "Processor Information"
	CounterTypeMemory           CounterType = "Memory"
	CounterTypeProcess          CounterType = "Process"
	CounterTypeNetworkInterface CounterType = "Network Interface"
	CounterTypePhysicalDisk     CounterType = "PhysicalDisk"
)

type CounterFieldType string

const (
	ProcessorUtility CounterFieldType = "% Processor Utility" // Processor Information

	AvailableMBytes CounterFieldType = "Available MBytes" // Memory

	ProcessorTime      CounterFieldType = `% Processor Time` // Process
	HandleCount        CounterFieldType = "Handle Count"
	WorkingSetPrivate  CounterFieldType = "Working Set - Private"
	ElapsedTime        CounterFieldType = "Elapsed Time"
	CreatingProcessID  CounterFieldType = "Creating Process ID"
	IDProcess          CounterFieldType = "ID Process"
	IOReadBytesPerSec  CounterFieldType = "IO Read Bytes/sec"
	IOWriteBytesPerSec CounterFieldType = "IO Write Bytes/sec"
	ThreadCount        CounterFieldType = "Thread Count"

	BytesReceivedPerSec CounterFieldType = "Bytes Received/sec" // Network Interface
	BytesSentPerSec     CounterFieldType = "Bytes Sent/sec"
	CurrentBandwidth    CounterFieldType = "Current Bandwidth"

	DiskTime              CounterFieldType = `% Disk Time` // PhysicalDisk
	AvgDiskBytesPerRead   CounterFieldType = "Avg. Disk Bytes/Read"
	AvgDiskBytesPerWrite  CounterFieldType = "Avg. Disk Bytes/Write"
	AvgDiskSecPerTransfer CounterFieldType = "Avg. Disk sec/Transfer" // 响应时间
	DiskTransfersPerSec   CounterFieldType = "Disk Transfers/sec"     // 传输速率

)
